<?php

use Yaf\Application;
use Yaf\Dispatcher;
use Yaf\Registry;
use Yaf\Session;
use Yaf\Config\Ini;
use Zend\Db\Adapter\Adapter as ZendDbAdapter;

class Bootstrap extends \Yaf\Bootstrap_Abstract {

    /**
     * Yaf的配置缓存
     *
     * @var \Yaf\Config\Ini
     */
    protected $config = null;

    /**
     * 把配置存到注册表
     *
     * @return void
     */
    public function _initConfig() {
        $config = Application::app()->getConfig();

        $this->config = $config;
        Registry::set('config', $config);
    }

    /**
     * IP白名单设置
     */
    public function _initIp() {
        // IP白名单设置
        \Yaf\Registry::set('ipwhitelist', new \Yaf\Config\Ini(APPLICATION_PATH . '/conf/ipwhitelist.ini', Application::app()->environ()));
    }

    /**
     * 重新设置一些PHP配置
     */
    public function _initPhpIni() {
        $phpSettings = $this->config->get('phpSettings');

        if ($phpSettings instanceof Ini) {
            foreach ($phpSettings->toArray() as $key => $value) {
                $this->phpIniSet($key, $value);
            }
        }
    }

    /**
     * 处理会话
     * Session 直接交由Yaf自带的类去处理.
     */
    public function _initSession() {
        $session = Session::getInstance();

        Registry::set('session', $session);
    }

    /**
     * 设置ini
     *
     * @param string $key       配置项.
     * @param mixed  $val       配置值.
     * @param string $prefix    用于和 "$key" 拼接 "." 连接符
     */
    public function phpIniSet($key, $val = null, $prefix = '') {
        $prefix .= $prefix ? ('.' . $key) : $key;

        if (is_array($val)) {
            foreach ($val as $k => $v) {
                $this->phpIniSet($k, $v, $prefix);
            }
        } else {
            ini_set($prefix, $val);
        }
    }

    /**
     * 注册本地类
     */
    public function _initRegisterLocalNamespace() {
        \Yaf\Loader::getInstance()->registerLocalNamespace(['Zend', 'Lib']);
    }

    /**
     * 通过派遣器得到默认的路由器
     *
     * @param \Yaf\Dispatcher $dispatcher
     */
    public function _initRoute(Dispatcher $dispatcher) {
        $router = $dispatcher->getRouter();

        if ($this->config->routes) {
            $router->addConfig($this->config->routes);
        }

        $router->addRoute('pmvc', new \Lib\Route());
    }

    /**
     * 连接 MySQL
     *
     * @description 读取不到数据库配置参数时, 这里应该抛异常, 并中止执行.
     */
    public function _initMySQL() {
        $conf = $this->config->get('resources.database.default');

        if (!$conf) {
            throw new \Exception('Not database configure', 503);
        }

        $dbAdapter = new ZendDbAdapter($conf->toArray());

        Registry::set('dbAdapter', $dbAdapter);
    }

    /**
     * 注册插件
     *
     * @param \Yaf\Dispatcher $dispatcher
     */
    public function _initPlugin(Dispatcher $dispatcher) {
        $plugins = explode(',', $this->config->get('application.plugins'));

        foreach ($plugins as $plugin) {
            if(!empty($plugin)) {
                $pluginName = sprintf('\\%sPlugin', $plugin);

                $dispatcher->registerPlugin(new $pluginName);
            }
        }
    }

    /**
     * 设置Layout
     *
     * @param \Yaf\Dispatcher $dispatcher
     */
    public function _initLayout(Dispatcher $dispatcher) {
        $layout = new \Lib\Layout($this->config->get('application.layout.directory'));
        $dispatcher->setView($layout);
        Registry::set('layout', $layout);
    }

    /**
     * Redis数据库
     *
     * @throws Exception 'Redis is need redis Extension!
     */
    public function _initRedis() {
        if (!extension_loaded('redis')) {
            throw new \Exception('Redis is need redis Extension!');
        }

        $conf = $this->config->get('resources.redis');

        if (!$conf) {
            throw new \Exception('Not redis configure!', 503);
        }

        $redis = new \Redis();

        if ($conf->get('port')) {
            $status = $redis->pconnect($conf->get('host'), $conf->get('port'));
        } else {
            $status = $redis->pconnect($conf->get('host'));
        }

        if (!$status) {
            throw new \Exception('Unable to connect to the redis:' . $conf->get('host'));
        }

        if ($conf->get('auth')) {
            $redis->auth($conf->get('auth'));
        }

        if ($conf->get('db')) {
            $redis->select($conf->get('db'));
        }

        if ($conf->get('options.prefix')) {
            $redis->setOption(\Redis::OPT_PREFIX, $conf->get('options.prefix'));
        }

        Registry::set('redis', $redis);
    }
}
